<?php
namespace App\Api\Controllers\HuiPay;


use App\Api\Rsa\RsaE;
use Illuminate\Support\Facades\Log;

class BaseController
{
    const HUIPAY_TEST_URL = 'https://mcsmtest.cloudpnr.com'; //测试
    const HUIPAY_TEST_PAY_URL = 'https://mcspptest.cloudpnr.com'; //支付测试
    const HUIPAY_URL = 'https://mcspm.cloudpnr.com'; //生产
    const HUIPAY_PAY_URL = 'https://mcspp.cloudpnr.com'; //支付生产

    //交易接口
    public $user_info = self::HUIPAY_TEST_PAY_URL.'/api/mcsproxypay/v1/channelUserIdQuery';  //用于获取微信、支付宝、银联正扫支付时的用户id
    public $front_scan = self::HUIPAY_TEST_PAY_URL.'/api/mcsproxypay/v1/usersweep/';  //用于微信、支付宝、银联正扫支付
    public $back_scan = self::HUIPAY_TEST_PAY_URL.'/api/mcsproxypay/v1/bizscan/';  //用于微信、支付宝、银联反扫支付
    public $user_refund = self::HUIPAY_TEST_PAY_URL.'/api/mcsproxypay/v1/refund/';  //用户进行扫码退款

    //查询接口
    public $order_info = self::HUIPAY_TEST_PAY_URL.'/api/mcsproxypay/v1/query';  //供商户查询其用户在本平台进行过的交易的交易状态

    //入驻类接口
    public $mer_apply_submit = self::HUIPAY_TEST_URL.'/api/mcsproxy/v1/mer/merApplySubmit';  //用户小微商户和代理商进件，共用接口，字段区分
    public $store_result = self::HUIPAY_TEST_URL.'/api/mcsproxy/v1/mer/merApplyResult';  //查询绑卡、微信入驻、支付宝入驻等的状态
    public $store_detail = self::HUIPAY_TEST_URL.'/api/mcsproxy/v1/mer/merDetail';  //商户信息查询
    public $modify_mer_apply = self::HUIPAY_TEST_URL.'/api/mcsproxy/v1/mer/merApplyModify';  //进件驳回后，修改进件的信息
    public $weixingzh = self::HUIPAY_TEST_URL.'/api/mcsproxy/v1/mer/merAddUserConf';  //单独公众号配置补入
    public $update_rate = self::HUIPAY_TEST_URL.'/api/mcsproxy/v1/mer/qrcpFeeUpdate';  //代理商修改商户的支付费率

    //文件上传接口
    public $upload_url = self::HUIPAY_TEST_URL.'/api/mcsproxy/v1/file/upload';  //图片上传

    //设备接口
    public $device_bind = self::HUIPAY_TEST_URL.'/api/mcsproxy/v1/device/bind';  //设备绑定
    public $device_unbind = self::HUIPAY_TEST_URL.'/api/mcsproxy/v1/device/unBind';  //设备解绑


    /**
     * 执行操作
     * @param string $url 请求地址
     * @param array $post_data 请求数据
     * @param array $sign_data 待签数据
     * @param string $privateKey 私钥
     * @param string $publicKey 公钥
     * @return array
     */
    public function execute($url, $post_data, $sign_data, $privateKey, $publicKey)
    {
        $post_data['sign'] = $this->rsa_sign($sign_data, $privateKey, 'RSA2');
        $post_data['data'] = str_replace('\\', '', json_encode($post_data['data'], JSON_UNESCAPED_UNICODE));
        $datajsonstr = str_replace("\\/", "/", json_encode($post_data, JSON_UNESCAPED_UNICODE)); //不转义中文和/
//print_r($datajsonstr);die;
//        Log::info('汇付入参：'.$datajsonstr);
//        Log::info('汇付入参请求地址：'.$url);
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); //访问超时时间
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $datajsonstr);
        curl_setopt($curl, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json; charset=UTF-8',
        ]);
        //本地忽略校验证书
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        $tmpInfo = curl_exec($curl);
        if ($tmpInfo) {
            $result = json_decode($tmpInfo, true);
//        print_r($result);die;
            if ($result['resp_code'] == '000000') {
                if ((isset($result['data'])) && (!empty($result['data']))) {
                    //没sign不用验签
                    if ((isset($result['sign'])) && (!empty($result['sign']))) {
                        $new_sign = $result['sign'];
                        if ($this->verify($sign_data, $new_sign, $publicKey)) {
                            return [
                                'status'=>$result['resp_code'],
                                'message'=>$result['resp_desc'],
                                'data'=>$result['data'],
                            ];
                        } else {
                            return [
                                'status' => '0',
                                'message' => $result['resp_desc']
                            ];
                        }
                    } else {
                        return [
                            'status' => $result['resp_code'],
                            'message' => $result['resp_desc'],
                            'data'=>$result['data'],
                        ];
                    }

                } else {
                    return [
                        'status' => $result['resp_code'],
                        'message' => $result['resp_desc']
                    ];
                }
            } else {
                return [
                    'status' => $result['resp_code'],
                    'message' => $result['resp_desc']
                ];
            }
        } else {
            return [
                'status' => '0',
                'message' => '汇付接口无返回值'
            ];
        }

    }


    /**
     * 生成 sha256WithRSA 签名
     * @param $content
     * @param $private_key
     * @param string $type
     * @return string
     */
    function rsa_sign($content, $private_key, $type = 'RSA2')
    {
        $data = $this->unset_arr($content);
        ksort($data);
        $new_data = str_replace("\\/", "/", json_encode($data, JSON_UNESCAPED_UNICODE)); //不转义中文和/

        $search = [
            "-----BEGIN RSA PRIVATE KEY-----",
            "-----END RSA PRIVATE KEY-----",
            "\n",
            "\r",
            "\r\n"
        ];
        $private_key = str_replace($search, "", $private_key);
        $private_key = $search[0] . PHP_EOL . wordwrap($private_key, 64, "\n", true) . PHP_EOL . $search[1];
        $res = openssl_pkey_get_private ($private_key);
        if ($res) {
            if ($type == 'RSA') {
                openssl_sign($new_data, $sign,$res);
            } elseif($type == 'RSA2') {
                openssl_sign($new_data, $sign,$res,OPENSSL_ALGO_SHA256);
            }
            openssl_free_key($res);
        } else {
            exit("私钥格式有误");
        }
        $sign = base64_encode($sign);
        return $sign;
    }


    /**
     * 验证 sha256WithRSA 签名
     * @param array $content 验签参数
     * @param string $sign 返回签名
     * @param $publicKey 公钥
     * @param string $type
     * @return string
     */
    public function verify($content, $sign, $publicKey, $type = 'RSA2')
    {
        $data = $this->unset_arr($content);
        ksort($data);
        $new_data = str_replace("\\/", "/", json_encode($data, JSON_UNESCAPED_UNICODE)); //不转义中文和/

        $search = [
            "-----BEGIN RSA PUBLIC KEY-----",
            "-----END RSA PUBLIC KEY-----",
            "\n",
            "\r",
            "\r\n"
        ];
        $public_key = str_replace($search, "", $publicKey);
        $public_key = $search[0] . PHP_EOL . wordwrap($public_key, 64, "\n", true) . PHP_EOL . $search[1];
        $res = openssl_pkey_get_public($public_key);
        if ($res) {
            if ($type == 'RSA') {
                openssl_verify($new_data, base64_decode($sign), $res);
            } elseif($type == 'RSA2') {
                openssl_verify($new_data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256);
            }
            openssl_free_key($res); //释放密钥资源
        } else {
            return json_encode([
                'status' => '0',
                'message' => "公钥格式有误"
            ]);
        }
        $sign = base64_encode($sign);
        return $sign;
    }


    /**
     * 去掉加签参数中二维数组以上的参数值
     * @param array $arr
     * @return string
     */
    function unset_arr($arr)
    {
        if (is_array($arr)) {
            $new_arr = [];
            foreach ($arr as $key => $value) {
                if (!is_array($value)) {
                    $new_arr[$key] = $value;
                }
            }
            return $new_arr;
        } else {
            return json_encode([
                'status'=>'2',
                'message'=>'参数不是数组'
            ]);
        }
    }


}
